package com.kly.user.rulePolicy;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.fqgj.exception.common.ApplicationException;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.api.client.util.Lists;
import com.kly.user.db.dao.TRuleHistoryLogDao;
import com.kly.user.db.entity.TRuleHistoryLogEntity;
import com.kly.user.db.entity.UserBehaviorLogEntity;
import com.kly.user.enums.LikeEnum;
import com.kly.user.enums.LogActionEnum;
import com.kly.user.rulePolicy.enums.DecisionResultEnum;
import com.kly.user.rulePolicy.enums.PolicyComposeEnum;
import com.kly.user.rulePolicy.enums.VariableTypeEnum;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 决策处理类
 * @author linqu
 */
@Service
public class DecisionAPITest {

    public static final Log logger = LogFactory.getLog(DecisionAPITest.class);


    @Resource
    ExecutePolicyService executePolicyService;


    public PolicySet decisionResult(DecisionVO decisionVo) {

        logger.info("规则执行开始：{}", JSONObject.toJSONString(decisionVo));
        List<Column> columns = decisionVo.getColumns();


        // 变量有效性校验
        columnListVerify(columns);
        PolicySet policySet = processPolicySet(buildPolicySet(decisionVo.getColumns()));


        return policySet;

    }



    public PolicySet processPolicySet(PolicySet policySet) {
        logger.info("规则策略及完整参数: {}", JSONObject.toJSONString(policySet));
        // 获取PolicySet采用的匹配类型
        PolicyComposeEnum policyCompose = PolicyComposeEnum.transformByName(policySet.getPolicyCompose());
        if (Objects.isNull(policyCompose)) {
            throw new ApplicationException("未设置匹配类型。");
        }

        // 获取策略集合
        List<Policy> policySetList = policySet.getPolicyList();

        // 首次匹配规则执行逻辑：WLM下发规则采用首次匹配
        final List<Policy> policyResults = policySetList.stream()
                .map(p -> new ExecutePolicyService().processPolicy(p)).collect(Collectors.toList());

        boolean policySetResult = false;
        if (policyCompose.equals(PolicyComposeEnum.FIRST)) {
            policySetResult = policyResults.stream().anyMatch(o -> o.getPolicyResult().equals(DecisionResultEnum.PASS.getType()));
        }
        if (policyCompose.equals(PolicyComposeEnum.WORST)) {
            policySetResult = policyResults.stream().allMatch(o -> o.getPolicyResult().equals(DecisionResultEnum.PASS.getType()));
        }

        if (policySetResult) {
            policySet.setPolicySetResult(DecisionResultEnum.PASS.getType());
        } else {
            policySet.setPolicySetResult(DecisionResultEnum.REJECT.getType());
        }


        return policySet;
    }

    private List<Column> columnListVerify(List<Column> columnList) {

        // TODO: 2023/6/23 检查传入的变量是否与nacos里配置的一致
        return columnList;

    }

//    @NacosValue("${user.wlm.policy}")
    private static String policySetStr;
    /**
     * 规则配置文件
     */
    public PolicySet buildPolicySet(List<Column> columnList) {

        //入参  变量
        if (StringUtils.isBlank(policySetStr)) {
            throw new ApplicationException("未配置策略");
        }

        for (Column column : columnList) {
            policySetStr = policySetStr.replaceAll("#" + column.getColumnCode() + "#", String.valueOf(column.getColumnValue()));
        }

        return JSONObject.parseObject(policySetStr, PolicySet.class);
    }

    public static void main(String[] args) {
        DecisionVO decisionVO = DecisionVO.builder().userCode("1212").apiReqId(UUID.randomUUID().toString()).build();
        List<Column> columns = Lists.newArrayList();
        /**
         * WLM下发策略变量参数提取
         */
        // 用户WLM个数
        final Column varWlmLikeTotalNum = Column.builder().columnCode("var_wlm_like_total_num")
                .columnType(VariableTypeEnum.INT.name()).columnValue(0).build();
        columns.add(varWlmLikeTotalNum);

        // 用户注册时间距离当前时间间隔
        final Column distanceTimesBetweenRegisterAndCurrent = Column.builder().columnCode("var_distance_from_registe_to_current_times")
                .columnType(VariableTypeEnum.INT.name()).columnValue(9839).build();
        columns.add(distanceTimesBetweenRegisterAndCurrent);

        // 当日建联数
        final Column likeEachTotalNumToday = Column.builder().columnCode("var_like_each_num_today")
                .columnType(VariableTypeEnum.INT.name()).columnValue(0).build();
        columns.add(likeEachTotalNumToday);

        // 距离上次启动时间
        final Column distanceTimesBetweenLatestOperationAndCurrent = Column.builder().columnCode("var_distance_from_latest_to_current_times")
                .columnType(VariableTypeEnum.INT.name()).columnValue(5).build();
        columns.add(distanceTimesBetweenLatestOperationAndCurrent);

        // 5分钟内收到的wlm数量
        final Column receivedWlmNumIn5Min = Column.builder().columnCode("var_received_wlm_num_in_5_min")
                .columnType(VariableTypeEnum.INT.name()).columnValue(0).build();
        columns.add(receivedWlmNumIn5Min);


        /**
         * WLM防打扰策略变量参数提取
         */
        // 当日下发WLM数
        final Column hasSentWlmNumToday = Column.builder().columnCode("var_has_sent_wlm_num_today")
                .columnType(VariableTypeEnum.INT.name()).columnValue(0).build();
        columns.add(hasSentWlmNumToday);

        // 当日注册时间大于3min
        final Column distanceTimesBetweenRegisterAndCurrentToday = Column.builder().columnCode("var_distance_from_registe_to_current_times_today")
                .columnType(VariableTypeEnum.INT.name()).columnValue(5).build();
        columns.add(distanceTimesBetweenRegisterAndCurrentToday);


        // 用户在线且距离上一次下发时间大于3min的wlm数量
        final Column sentWlmIn3Min = Column.builder().columnCode("var_online_and_distance_from_latest_send_to_current")
                .columnType(VariableTypeEnum.INT.name()).columnValue(0).build();
        columns.add(sentWlmIn3Min);

        // 用户离线且(6pm-8pm范围内的的随机时间点)以后距离上一次下发时间
        // 6pm-8pm之间的任意一个时间点
        final Column sentWlmInRandom6pmAnd8Pm = Column.builder().columnCode("var_offline_and_distance_from_latest_send_to_current")
                .columnType(VariableTypeEnum.INT.name()).columnValue(8).build();
        columns.add(sentWlmInRandom6pmAnd8Pm);

        decisionVO.setColumns(columns);
        if (StringUtils.isBlank(policySetStr)) {
            policySetStr = "{\"policySetId\":\"1231\",\"policySetName\":\"WLM下发策略\",\"policyCompose\":\"WORST\",\"policyList\":[{\"policyName\":\"允许WLM下发到客户端策略\",\"priority\":2,\"ruleCompose\":\"FIRST\",\"ruleList\":[{\"ruleName\":\"WLM数小于5个\",\"decisionResult\":{},\"conditionGroupCompose\":\"ALL\",\"conditions\":[{\"firstVariable\":{\"name\":\"var_wlm_like_total_num\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_wlm_like_total_num#\"},\"operation\":\"LT\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_wlm_like_total_num\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":5}}]},{\"ruleName\":\"注册时间大于3min\",\"decisionResult\":{},\"conditionGroupCompose\":\"ALL\",\"conditions\":[{\"firstVariable\":{\"name\":\"var_distance_from_registe_to_current_times\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_distance_from_registe_to_current_times#\"},\"operation\":\"GT\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_from_registe_time\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":3}}]},{\"ruleName\":\"当日未建联\",\"decisionResult\":{},\"conditionGroupCompose\":\"ALL\",\"conditions\":[{\"firstVariable\":{\"name\":\"var_like_each_num_today\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_like_each_num_today#\"},\"operation\":\"EQ\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_like_each_num\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":0}}]},{\"ruleName\":\"距离上次启动时间大于3min且5分钟之内未收到新的WLM\",\"decisionResult\":{},\"conditionGroupCompose\":\"ALL\",\"conditions\":[{\"firstVariable\":{\"name\":\"var_distance_from_latest_to_current_times\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_distance_from_latest_to_current_times#\"},\"operation\":\"GT\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_from_latest_action_time\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":3}},{\"firstVariable\":{\"name\":\"var_received_wlm_num_in_5_min\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_received_wlm_num_in_5_min#\"},\"operation\":\"EQ\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_received_wlm_num_in_5_min\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":0}}]}]},{\"policyName\":\"WLM下发防打扰策略\",\"ruleCompose\":\"WORST\",\"priority\":1,\"ruleList\":[{\"ruleName\":\"当日下发WLM数小于5个\",\"decisionResult\":{},\"conditionGroupCompose\":\"ALL\",\"conditions\":[{\"firstVariable\":{\"name\":\"var_has_sent_wlm_num_today\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_has_sent_wlm_num_today#\"},\"operation\":\"LT\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_has_sent_wlm_num_today\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":5}}]},{\"ruleName\":\"当日注册时间大于3min\",\"decisionResult\":{},\"conditionGroupCompose\":\"ALL\",\"conditions\":[{\"firstVariable\":{\"name\":\"var_distance_from_registe_to_current_times_today\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_distance_from_registe_to_current_times_today#\"},\"operation\":\"GT\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_regist_time\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":3}}]},{\"ruleName\":\"当日建联数小于5\",\"decisionResult\":{},\"conditionGroupCompose\":\"ALL\",\"conditions\":[{\"firstVariable\":{\"name\":\"var_like_each_num_today\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_like_each_num_today#\"},\"operation\":\"LT\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_like_each_num_today\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":5}}]},{\"ruleName\":\"在线且距离上一次下发时间大于3min或离线且 (6pm-8-pm范围内的的随机时间点)以后距离上一次下发时间大于2h \",\"decisionResult\":{},\"conditionGroupCompose\":\"ANY\",\"conditions\":[{\"firstVariable\":{\"name\":\"var_online_and_distance_from_latest_send_to_current\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_online_and_distance_from_latest_send_to_current#\"},\"operation\":\"GT\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_between_latest_send_times\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":3}},{\"firstVariable\":{\"name\":\"var_offline_and_distance_from_latest_send_to_current\",\"varType\":\"INT\",\"opType\":\"VARIABLE\",\"value\":\"#var_offline_and_distance_from_latest_send_to_current#\"},\"operation\":\"GT\",\"conditionCompose\":\"AND\",\"secondVariable\":{\"name\":\"cnst_between_latest_send_time_hours\",\"varType\":\"INT\",\"opType\":\"CONSTANT\",\"value\":2}}]}]}]}\n";
        }
        final PolicySet policySet = new DecisionAPITest().decisionResult(decisionVO);


        System.out.println(JSONObject.toJSONString(policySet));


    }

}
